package cc.bukkitPlugin.banitem.manager;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.bukkit.Material;
import org.bukkit.command.CommandSender;
import org.bukkit.configuration.ConfigurationSection;

import cc.bukkitPlugin.banitem.BanItem;
import cc.bukkitPlugin.banitem.BanItemEnume.ListType;
import cc.bukkitPlugin.banitem.check.Damage;
import cc.bukkitPlugin.banitem.check.DamageList;
import cc.bukkitPlugin.banitem.check.SimpleWorld;
import cc.bukkitPlugin.banitem.check.WorldTypeItem;
import cc.bukkitPlugin.util.LocalLanguage;
import cc.bukkitPlugin.util.config.CommentedSection;
import cc.bukkitPlugin.util.config.CommentedYamlConfig;
import cc.bukkitPlugin.util.plugin.ABukkitPlugin;
import cc.bukkitPlugin.util.plugin.AManager;
import cc.bukkitPlugin.util.plugin.INeedConfig;
import cc.bukkitPlugin.util.plugin.fileManager.AFileManager;

public class ItemManager extends AManager<BanItem> implements INeedConfig{

    public static final char reChar='$';
    public static final String WORLD_ITEM_DIR="WorldItem"+File.separator;;
    private static final String ID_NODE="CurrentId";
    private static final String NAME_NODE="CurrentName";
    /**Key为null的为默认配置,key全部使用小写*/
    private final HashMap<SimpleWorld,HashSet<ListType>> mWorldsItemSelfCfg=new HashMap<>();
    /**Key为null的为默认配置*/
    private final HashMap<SimpleWorld,HashMap<ListType,WorldTypeItem>> mWorldsItems=new HashMap<>();

    public ItemManager(BanItem pPlugin){
        super(pPlugin);
        this.mPlugin.registerConfigModel(this);
    }

    public BanItem getPlugin(){
        return this.mPlugin;
    }

    @Override
    public void setConfig(CommandSender pSender){
        this.mWorldsItemSelfCfg.clear();
        CommentedYamlConfig tConfig=this.mPlugin.getConfigManager().getConfig();
        CommentedSection tSection=tConfig.getConfigurationSection("WorldItemListNotInherit");
        if(tSection==null)
            return;
        for(String sWorldKey : tSection.getKeys(false)){
            List<String> tLists=tSection.getStringList(sWorldKey);
            if(tLists==null||tLists.isEmpty())
                continue;
            HashSet<ListType> tListType=new HashSet<>(3);
            for(String sListType : tLists){
                ListType sType=ListType.getTypeByListName(sListType);
                if(sType==null){
                    ABukkitPlugin.severe(pSender,"在世界["+sWorldKey+"]配置中,物品列表类型["+sListType+"]不是预定义的列表类型");
                }else tListType.add(sType);
            }
            if(!tListType.isEmpty())
                this.mWorldsItemSelfCfg.put(SimpleWorld.create(sWorldKey),tListType);
        }
        this.mWorldsItemSelfCfg.put(SimpleWorld.defaultWorld,ListType.getEnumes());
        this.reloadConfig(pSender);
    }

    /**
     * 重载世界物品列表
     * @param pSender 命令发起者
     */
    public void reloadConfig(CommandSender pSender){
        File tWorldItemDir=new File(this.mPlugin.getDataFolder(),ItemManager.WORLD_ITEM_DIR);
        if(!tWorldItemDir.isDirectory()){
            tWorldItemDir.mkdirs();
        }
        for(Map.Entry<SimpleWorld,HashSet<ListType>> sEntry : this.mWorldsItemSelfCfg.entrySet()){
            if(sEntry.getValue().isEmpty())
                continue;
            HashMap<ListType,WorldTypeItem> tWorldTypesItems=this.mWorldsItems.get(sEntry.getKey());
            if(tWorldTypesItems==null){
                tWorldTypesItems=new HashMap<>(3);
                this.mWorldsItems.put(sEntry.getKey(),tWorldTypesItems);
            }
            for(ListType sListType : sEntry.getValue()){
                WorldTypeItem tWorldTypeItem=tWorldTypesItems.get(sListType);
                if(tWorldTypeItem==null){
                    tWorldTypeItem=new WorldTypeItem(this,sEntry.getKey(),sListType);
                    tWorldTypesItems.put(sListType,tWorldTypeItem);
                }
                tWorldTypeItem.reloadConfig(pSender);
            }
        }
    }

    /**
     * 返回指定世界指定类型的列表
     * <p>
     * 如果指定的世界或指定的列表不存在,返回默认列表
     * </p>
     * @param pWorld 指定的世界名,如果null则为默认
     * @param pListType 列表类型
     * @return 世界类型列表,非null
     */
    public WorldTypeItem getWorldTypeItem(SimpleWorld pWorld,ListType pListType){
        HashSet<ListType> worldCfg=this.mWorldsItemSelfCfg.get(pWorld);
        if(worldCfg!=null&&worldCfg.contains(pListType))
            return this.mWorldsItems.get(pWorld).get(pListType);
        return this.mWorldsItems.get(SimpleWorld.defaultWorld).get(pListType);
    }

    /**
     * 从指定的短文件名载入物品
     * @param pConfig 要保存到的配置管理器
     * @param pListType 物品类型
     * @return 载入的物品列表,如果载入失败,将返回null
     */
    public HashMap<Material,DamageList> loadItemFromConfig(CommentedYamlConfig pConfig,ListType pListType){
        HashMap<Material,DamageList> items=new HashMap<>();
        for(String itemkey : pConfig.getKeys(false)){
            if(itemkey.equals(AFileManager.SEC_CFG_VERSION))
                continue;
            ConfigurationSection itemSec=pConfig.getConfigurationSection(itemkey);
            Material material=ItemManager.getMaterial(itemkey);
            if(material==null){
                ABukkitPlugin.warn("配置项: "+itemkey+"物品不存在,将会在下次保存时移除");
                continue;
            }
            if(itemSec==null)
                continue;
            DamageList damages=items.get(material);
            if(damages==null){
                damages=new DamageList(material);
                items.put(material,damages);
            }
            for(String skeyDamage : itemSec.getKeys(false)){
                if(skeyDamage.equalsIgnoreCase(ID_NODE))
                    continue;
                short damageValue=-1;
                if(!skeyDamage.matches("((?i)damage)@-?\\d+")){
                    ABukkitPlugin.warn("配置项: "+itemkey+": "+skeyDamage+"格式错误,应为[damage@数字],其中数字必须为short类型");
                    continue;
                }
                try{
                    damageValue=Short.parseShort(skeyDamage.substring(7));
                }catch(NumberFormatException nfexp){
                    ABukkitPlugin.warn("配置项: "+itemkey+": "+skeyDamage+"格式错误,应为[damage@数字],其中数字必须为short类型");
                    continue;
                }
                Damage tDamage=new Damage(damageValue,pListType);
                damages.add(tDamage);
                ConfigurationSection damageSec=itemSec.getConfigurationSection(skeyDamage);
                if(damageSec==null)
                    continue; //damage节点下无任何值
                if(!pListType.isSimpleNode()){
                    tDamage.setReason(damageSec.getString("reason"));
                    ConfigurationSection nbtSecs=damageSec.getConfigurationSection("nbt");
                    if(nbtSecs==null)
                        continue; //不存在NBT限制
                    for(String nbtkey : nbtSecs.getKeys(false)){
                        ArrayList<String> nbtRawValueList=(ArrayList<String>)nbtSecs.getStringList(nbtkey);
                        if(nbtRawValueList.size()==0){
                            nbtSecs.set(nbtkey,null);
                            ABukkitPlugin.warn("配置项: "+itemkey+": "+skeyDamage+": "+nbtkey+"下没有任何值,已移除");
                            continue;
                        }
                        tDamage.putNBTValues(nbtkey.replace(reChar,'.'),nbtRawValueList);
                    }
                }
            }
        }
        return items;
    }

    /**
     * 从指定的字符串数组载入物品
     * <p>此函数只用于配置文件升级时使用</p>
     * @param itemList 字符串数组
     * @return 载入的物品
     */
    @Deprecated
    public HashMap<Material,DamageList> getSimpleItem(List<String> itemList){
        HashMap<Material,DamageList> items=new HashMap<>();
        if(itemList==null)
            return items;
        for(String strItem : itemList){
            String args[]=strItem.split(":");
            Material material=ItemManager.getMaterial(args[0]);
            if(material==null){
                ABukkitPlugin.warn("配置项: "+strItem+"物品不存在,将会在下次保存时移除");
                continue;
            }
            short damageValue=-1;
            if(args.length>1)
                try{
                    damageValue=Short.parseShort(args[1]);
                }catch(NumberFormatException nfexp){}
            DamageList damages=items.get(material);
            if(damages==null){
                damages=new DamageList(material);
                items.put(material,damages);
            }
            damages.add(new Damage(damageValue,ListType.NBT));
        }
        return items;
    }

    /**
     * 将items中的数据保存到文件中
     * @param pConfig 要保存到的配置管理器
     * @param pItems 要存入的数据
     * @return 是否保存成功
     */
    public void saveItemToConfig(CommentedYamlConfig pConfig,HashMap<Material,DamageList> pItems){
        pConfig.clear();
        for(Iterator<Entry<Material,DamageList>> it=pItems.entrySet().iterator();it.hasNext();){
            Entry<Material,DamageList> entry=it.next();
            if(entry.getValue().isEmpty()){ //不存在任何子id
                it.remove();
                continue;
            }
            String itemname=entry.getKey().name();
            ConfigurationSection itemsec=pConfig.createSection(itemname);
            itemsec.set(ID_NODE,entry.getKey().getId());
            LocalLanguage<?> tLang=LocalLanguage.getInstance(this.mPlugin);
            for(Damage sDamage : entry.getValue().values()){
                ConfigurationSection damageSec=itemsec.createSection("damage@"+sDamage.mValue);

                damageSec.set(ItemManager.NAME_NODE,tLang.getName(entry.getKey(),sDamage.mValue));
                if(sDamage.isSimpleNode())
                    continue;

                damageSec.set("reason",sDamage.getReason());
                ConfigurationSection NBTSec=damageSec.createSection("nbt");
                for(String nbt : sDamage.getNBTLabelSet())
                    NBTSec.set(nbt.replace('.',reChar),new ArrayList<>(sDamage.getRawNBTValues(nbt)));
            }
        }
    }

    /**
     * 依照输入的字符串获得Material
     * <p>
     * 默认先以文本的形式转换字符串为Material,如果Material为null或者为Material.Air,则
     * 尝试将文本转换为数字并使用Material.getMaterial(int)的方法获取Material,如果都为
     * null或者Material.Air,那么返回null
     * </p>
     * @param value 要转换的字符串
     * @return 转换后的 Material
     */
    private static Material getMaterial(String value){
        Material material=Material.getMaterial(value);
        if(material!=null&&material!=Material.AIR)
            return material;
        try{
            int key=Integer.parseInt(value);
            material=Material.getMaterial(key);
        }catch(NumberFormatException nbfexp){
            return null;
        }
        if(material==null||material==Material.AIR){
            return null;
        }else return material;
    }

}
